/**
 * Anderground project - Subway maps processor application.
 * Copyright (C) 2008-2009 Eldar Abusalimov, Ilya Shurigyn
 * 
 * This file is part of Anderground.
 * 
 * Anderground is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * Anderground is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Anderground.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.anderground.modules.drawer.dynamic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.anderground.core.drawer.Calculator;
import org.anderground.core.drawer.Calculator.Mode;
import org.anderground.core.model.Hub;
import org.anderground.core.model.ModelData;
import org.anderground.core.model.Station;
import org.anderground.core.model.Transfer;
import org.anderground.core.model.Transition;
import org.anderground.core.model.Tunnel;

/**
 * This class represents entire {@link ModelData}, holding such objects as
 * {@link Crossing}s (respond for drawing of {@link Station}s and {@link Hub}s)
 * and {@link Road}s (drawing {@link Transition}s between Crossings)
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
class Structure {

	private HashMap<Station, SimpleAmoeba> simpleAmoebasMap;

	private HashMap<Transition, SimpleBacillus> simpleBacillusMap;

	private ArrayList<Crossing> crossings = new ArrayList<Crossing>();

	private ArrayList<Road> roads = new ArrayList<Road>();

	public Structure(ModelData modelData, Mode mode) {

		simpleAmoebasMap = new HashMap<Station, SimpleAmoeba>(modelData
				.getStations().size(), 1);

		for (Hub hub : modelData.getHubs()) {
			Crossing crossing = new Crossing(hub, mode, this);
			simpleAmoebasMap.putAll(crossing.getSimpleAmoebasMap());
		}

		for (Station station : modelData.getStations()) {
			if (station.getHub() == null) {
				Crossing crossing = new Crossing(station, mode, this);
				simpleAmoebasMap.putAll(crossing.getSimpleAmoebasMap());
			}
		}

		simpleBacillusMap = new HashMap<Transition, SimpleBacillus>(
				modelData.getTunnels().size() + modelData.getTunnels().size(),
				1);

		for (Tunnel tunnel : modelData.getTunnels()) {
			SimpleAmoeba fromAmoeba = simpleAmoebasMap.get(tunnel
					.getFromStation());
			SimpleAmoeba toAmoeba = simpleAmoebasMap.get(tunnel
					.getToStation());
			SimpleBacillus bacillus = fromAmoeba
					.searchSimpleBacillus(toAmoeba);
			bacillus.addTunnel(fromAmoeba, toAmoeba, tunnel);
			simpleBacillusMap.put(tunnel, bacillus);
		}

		for (Transfer transfer : modelData.getTransfers()) {
			SimpleAmoeba fromAmoeba = simpleAmoebasMap.get(transfer
					.getFromStation());
			SimpleAmoeba toAmoeba = simpleAmoebasMap.get(transfer
					.getToStation());
			SimpleBacillus bacillus = fromAmoeba
					.searchSimpleBacillus(toAmoeba);
			bacillus.addTransfer(fromAmoeba, toAmoeba, transfer);
			simpleBacillusMap.put(transfer, bacillus);
		}

		for (Road road : roads) {
			road.build();
		}

	}

	void addRoad(Road road) {
		roads.add(road);
	}

	void addCrossing(Crossing crossing) {
		crossings.add(crossing);
	}

	public void applyCalculator(Calculator calculator) {
		for (Crossing amoeba : crossings) {
			amoeba.applyCalculator(calculator);
		}
	}

	public Amoeba getStationMapping(Station station) {
		return simpleAmoebasMap.get(station);
	}

	public Bacillus getTransitionMapping(Transition transition) {
		return simpleBacillusMap.get(transition);
	}

	public ArrayList<Amoeba> getDrawnAmoebas() {
		ArrayList<Amoeba> drawnAmoebas = new ArrayList<Amoeba>();
		for (Crossing crossing : crossings) {
			crossing.addDrawnAmoebas(drawnAmoebas);
		}
		return drawnAmoebas;
	}

	public List<Crossing> getCrossings() {
		return crossings;
	}

	public List<Road> getRoads() {
		return roads;
	}

}
